home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / nn.zip / INIT.C < prev    next >
C/C++ Source or Header  |  1989-12-31  |  19KB  |  997 lines

  1. /*
  2.  *    .nn/init file handling
  3.  */
  4.  
  5.  
  6. #include "config.h"
  7. #include "articles.h"
  8. #include "term.h"
  9. #include "keymap.h"
  10. #include "menu.h"
  11.  
  12. export int in_init = 0;        /* true when parsing init file */
  13. export int alt_cmd_key;        /* K_ when parse_command returns AC_KEYCMD */
  14.  
  15. static int init_err = 0;    /* errors in init file */
  16.  
  17.  
  18. /*VARARGS*/
  19. init_message(va_alist)
  20. va_dcl
  21. {
  22.     char *fmt;
  23.     va_list ap;
  24.     
  25.     va_start(ap);
  26.     
  27.     if (in_init) {
  28.     fmt = va_arg1(char *);
  29.  
  30.     printf("init error: ");
  31.     vprintf(fmt, va_args2toN);
  32.     putchar(NL);
  33.     init_err++;
  34.     } else
  35.     vmsg(va_args1toN);
  36.  
  37.     va_end(ap);
  38. }
  39.  
  40.     
  41. visit_init_file(only_seq)
  42. int only_seq;
  43. {
  44.     extern FILE *loc_seq_hook, *glob_seq_hook;
  45.     in_init = 1;
  46.     load_init_file(relative(lib_directory, "init"), &glob_seq_hook, only_seq);
  47.     load_init_file("init", &loc_seq_hook, only_seq);
  48.     if (init_err) nn_exit(1);
  49.     in_init = 0;
  50. }
  51.  
  52.  
  53. #define START_SEQUENCE 555
  54.  
  55.  
  56. static load_init_file(name, seq_hook_ptr, only_seq)
  57. char *name;
  58. FILE **seq_hook_ptr;
  59. {
  60.     FILE *init;
  61.     char cmdbuf[512], *cmd, *term;
  62.     extern char *term_name;
  63.  
  64.     /* use cmdbuf temporarily (to handle @ expansion) */
  65.     for (cmd = cmdbuf; *name; name++)
  66.     if (*name == '@') {
  67.         term = term_name;
  68.         while (term && *term) *cmd++ = *term++;
  69.     } else
  70.         *cmd++ = *name;
  71.     *cmd = NUL;
  72.     name = cmdbuf;
  73.  
  74.     if (*name != '/')
  75.     name = relative(nn_directory, name);
  76.     
  77.     init = open_file(name, OPEN_READ);
  78.     if (init == NULL) return;
  79.  
  80.     while (fgets(cmdbuf, 512, init)) {
  81.     if (only_seq) {
  82.         if (!is_sequence(cmdbuf)) continue;
  83.         *seq_hook_ptr = init;
  84.         return;
  85.     }
  86.     /* we use AC_REDRAW to avoid !-commands clear the screen */
  87.     if (parse_command(cmdbuf, AC_REDRAW, init) == START_SEQUENCE) {
  88.         if (seq_hook_ptr) {
  89.         *seq_hook_ptr = init;
  90.         return;    /* no close !! */
  91.         } else {
  92.         init_message("load file contains 'sequence'");
  93.         fclose(init);
  94.         return;
  95.         }
  96.     }
  97.     }
  98.     
  99.     fclose(init);
  100. }
  101.  
  102.  
  103. #define MAXARG 10
  104.  
  105. static char *argvec[MAXARG + 2];
  106. static int argc;
  107.  
  108. static char *strip_str(cmd)
  109. register char *cmd;
  110. {
  111.     if (cmd == NULL) return cmd;
  112.  
  113.     while (*cmd && isspace(*cmd)) cmd++;
  114.     if (*cmd == NUL || *cmd == NL) return NULL;
  115.     
  116.     return cmd;
  117. }
  118.  
  119.     
  120. static split_command(cmd)
  121. register char *cmd;
  122. {
  123.     /* split command string */
  124.  
  125.     for (argc = 0; argc < MAXARG + 2; argc++) argvec[argc] = NULL;
  126. strip_more:
  127.     if ((cmd = strip_str(cmd)) == NULL || *cmd == '#') return 0;
  128.     if (*cmd == ':') {
  129.     cmd++;
  130.     goto strip_more;
  131.     }
  132.     
  133.     argc = 0;
  134.     argvec[0] = cmd;
  135.  
  136.     if (in_init)
  137.     while (*cmd) {
  138.         if (*cmd == NL) {
  139.         *cmd = NUL;
  140.         break;
  141.         }
  142.         cmd++;
  143.     }
  144.  
  145.     return 1;
  146. }
  147.  
  148. static char *argv(i)
  149. int i;
  150. {
  151.     register char *cmd;
  152.     
  153.     if (i > MAXARG) return NULL;
  154.     
  155.     if (argc <= i)
  156.     if (cmd = argvec[argc])
  157.         while (argc <= i) {
  158.         while (*cmd && !isspace(*cmd)) cmd++;
  159.         if (*cmd == NUL) {
  160.             argc = MAXARG;
  161.             break;
  162.         }
  163.         
  164.         *cmd++ = NUL;
  165.         if ((cmd = strip_str(cmd)) == NULL) {
  166.             argc = MAXARG;
  167.             break;
  168.         }
  169.         argvec[++argc] = cmd;
  170.         }
  171.     else
  172.         argc = MAXARG;
  173.  
  174.     return argvec[i];
  175. }
  176.  
  177. static is_sequence(cmd)
  178. char *cmd;
  179. {
  180.     if (!split_command(cmd)) return 0;
  181.     if ((cmd = argv(0)) == NULL) return 0;
  182.     return strcmp(cmd, "sequence") == 0;
  183. }
  184.  
  185.     
  186. /*
  187.  * parse a command (also :-commands)
  188.  */
  189.  
  190. static char *sw_string;
  191.  
  192. #define    SWITCH(str)    \
  193.     for (sw_string = str; sw_string; sw_string = NULL) 
  194.  
  195. #define CASE(str)    \
  196.     if (strcmp(sw_string, str) == 0)
  197.     
  198.  
  199. #define ARG(i, str)    (argv(i) && strcmp(argv(i), str) == 0)
  200. #define ARGVAL(i)    atol(argv(i))
  201. #define ARGTAIL        argvec[argc]
  202.  
  203. struct alt_commands {
  204.     char *alt_name;
  205.     int     alt_len;
  206.     int  alt_type;
  207. } alt_commands[] = {
  208.     "admin",            5,    0,
  209.     "cd",            2,    1,
  210.     "compile",            7,    0,
  211.     "coredump",            8,    0,
  212.     "decode",            6,    0,
  213.     "define",            6,    0,
  214.     "help",            4,    2,
  215.     "local",            5,    3,
  216.     "man",            3,    0,
  217.     "map",            3,    -1,
  218.     "map both",            8,    4,
  219.     "map key",            7,    0,
  220.     "map menu",            8,    4,
  221.     "map show",            8,    4,
  222.     "mkdir",            5,    1,
  223.     "patch",            5,    0, /* QUICK HACK */
  224.     "print",            5,    0, /* QUICK HACK */
  225.     "pwd",            3,    0,
  226.     "rmail",            5,    0,
  227.     "set",            3,    3,
  228.     "show",            4,    -1,
  229.     "show groups",        11,    -1,
  230.     "show groups all",        15,    0,
  231.     "show groups subscr",    18,    0,
  232.     "show groups total",    17,    0,
  233.     "show groups unsub",    17,    0,
  234.     "show kill",        9,    0,
  235.     "show map",            8,    -1,
  236.     "show map #",        10,    0,
  237.     "show map key",        12,    0,
  238.     "show map menu",        13,    0,
  239.     "show map show",        13,    0,
  240.     "sort",            4,    -1,
  241.     "sort age",            8,    0,
  242.     "sort arrival",        12,    0,
  243.     "sort subject",        12,    0,
  244.     "toggle",            6,    3,
  245.     "unread",            6,    0,
  246.     "unset",            5,    3,
  247.     "unshar",            6,    0, /* QUICK HACK */
  248.     NULL,            0,    0
  249. };
  250.  
  251. alt_completion(buf, index)
  252. char *buf;
  253. int index;
  254. {
  255.     static char *head, *tail = NULL, buffer[FILENAME];
  256.     static int len;
  257.     static struct alt_commands *alt, *help_alt;
  258.     static int (*other_compl)();
  259.     int temp;
  260.     register char *p, *q;
  261.     extern int file_completion(), var_completion(), cmd_completion();
  262.     extern int list_offset;
  263.     
  264.     if (other_compl) {
  265.     temp = (*other_compl)(buf, index);
  266.     if (index == 0 && temp == 1 && tail) strcpy(tail, head);
  267.     if (index < 0 || (index == 0 && temp == 0)) {
  268.         other_compl = NULL;
  269.         list_offset = 0;
  270.     }
  271.     return temp;
  272.     }
  273.     
  274.     if (index < 0) return 0;
  275.  
  276.     if (buf) {
  277.     head = buf;
  278.     tail = buf + index;
  279.     alt = help_alt = alt_commands;
  280.     len = tail - head;
  281.     other_compl = NULL;
  282.     
  283.     for (; alt->alt_name; alt++) {
  284.         if (len <= alt->alt_len || head[alt->alt_len] != SP) continue;
  285.         index = strncmp(alt->alt_name, head, alt->alt_len);
  286.         if (index < 0) continue;
  287.         if (index > 0) break;
  288.  
  289.         if (alt->alt_type < 0) {
  290.         if (len > alt->alt_len) continue;
  291.         break;
  292.         }
  293.         
  294.         if (alt->alt_type == 0) return -1; /* cannot be further compl */
  295.  
  296.         head += alt->alt_len;
  297.         while (*head && *head == SP) head++;
  298.         len = tail - head;
  299.         temp = -1;
  300.         
  301.         switch (alt->alt_type) {
  302.          case 1:
  303.         other_compl = file_completion;
  304.         tail = NULL;
  305.         temp = file_completion(head, len);
  306.         break;
  307.         
  308.          case 2:
  309.         other_compl = file_completion;
  310.         sprintf(buffer, "%s.%s",
  311.             relative(lib_directory, "help"), head);
  312.         len = strlen(buffer);
  313.         head = buffer + len;
  314.         list_offset = 5;
  315.         temp = file_completion(buffer, len);
  316.         break;
  317.         
  318.          case 3:
  319.         /* [set ]variable[ value] */
  320.         for (p = head; *p; ) 
  321.             if (*p++ == SP) return -1;
  322.         other_compl = var_completion;
  323.         tail = NULL;
  324.         temp = var_completion(head, len);
  325.         break;
  326.         
  327.          case 4:
  328.         /* [map XXX ]Y command[ N] */
  329.         for (p = head, temp = 0; *p; ) 
  330.             if (*p++ == SP) {
  331.             while (*p && *p == SP) p++;
  332.             head = p;
  333.             temp++;
  334.             }
  335.         if (temp != 1) return -1;
  336.  
  337.         other_compl = cmd_completion;
  338.         tail = NULL;
  339.         len = p - head;
  340.         temp = cmd_completion(head, len);
  341.         break;
  342.         }
  343.         if (temp <= 0) other_compl = NULL;
  344.         return temp;
  345.     }
  346.     
  347.     alt = alt_commands;
  348.     return 1;
  349.     }
  350.     
  351.     if (index) {
  352.     list_completion((char *)NULL);
  353.     if (help_alt->alt_name == NULL) help_alt = alt_commands;
  354.     list_offset = 0;
  355.     if (p = strrchr(head, ' ')) list_offset = p - head;
  356.     
  357.     while (help_alt->alt_name) {
  358.         if (len > help_alt->alt_len ||
  359.         (index = strncmp(help_alt->alt_name, head, len)) < 0) {
  360.         help_alt++;
  361.         continue;
  362.         }
  363.         if (index > 0) {
  364.         help_alt = alt_commands;
  365.         break;
  366.         }
  367.         p = help_alt->alt_name;
  368.         if (list_completion(p) == 0) break;
  369.         temp = help_alt->alt_len;
  370.     
  371.         do help_alt++;
  372.         while ((q = help_alt->alt_name) && help_alt->alt_len > temp &&
  373.            strncmp(p, q, temp) == 0);
  374.     }
  375.     fl;
  376.     list_offset = 0;
  377.     return 1;
  378.     }
  379.  
  380.     for (; alt->alt_name; alt++) {
  381.     if (len == 0) 
  382.         index = 0;
  383.     else
  384.         index = strncmp(alt->alt_name, head, len);
  385.     if (index < 0) continue;
  386.     if (index > 0) break;
  387.     
  388.     p = alt->alt_name;
  389.     sprintf(tail, "%s ", p + len);
  390.     temp = alt->alt_len;
  391.     
  392.     do alt++;
  393.     while ((q = alt->alt_name) && alt->alt_len > temp &&
  394.            strncmp(p, q, temp) == 0);
  395.     
  396.     return 1;
  397.     }
  398.     return 0;
  399. }
  400.  
  401.     
  402. parse_command(cmd, ok_val, initf)
  403. char *cmd;
  404. int ok_val;
  405. FILE *initf;
  406. {
  407.     extern char *m_define(), *parse_enter_macro();
  408.     int i;
  409.     
  410.     if (!split_command(cmd)) return ok_val;
  411.  
  412.     if (*ARGTAIL == '!') {
  413.     if (run_shell(ARGTAIL+1, 
  414.               ok_val == AC_PROMPT ? 1 :
  415.               ok_val == AC_UNCHANGED ? -1 : 0) && ok_val != AC_UNCHANGED) {
  416.         any_key(0);
  417.         return AC_REDRAW;
  418.     }
  419.     return ok_val;
  420.     }
  421.  
  422.     SWITCH( argv(0) ) {
  423.  
  424.     CASE( "unset" ) {
  425.         if (argv(1) == NULL) goto stx_err;
  426.         
  427.         if (set_variable(argv(1), 0, (char *)NULL))
  428.         return AC_REDRAW;
  429.         else
  430.         return ok_val;
  431.     }
  432.     
  433.     CASE( "local" ) {
  434.         if (ARGTAIL == NULL) goto stx_err;
  435.         
  436.         cmd = argv(1);
  437.         if (!push_variable(cmd)) return ok_val;
  438.         
  439.         if (ARGTAIL && set_variable(cmd, 1, ARGTAIL))
  440.         return AC_REDRAW;
  441.         else
  442.         return ok_val;
  443.     }
  444.         
  445.     CASE( "set" ) {
  446.         if (ARGTAIL == NULL) {
  447.         disp_variables();
  448.         return AC_REDRAW;
  449.         }
  450.  
  451.         cmd = argv(1);    /* get ARGTAIL right */
  452.         if (set_variable(cmd, 1, ARGTAIL))
  453.         return AC_REDRAW;
  454.         else
  455.         return ok_val;
  456.     }
  457.  
  458.     CASE( "toggle" ) {
  459.         if (argv(1) == NULL) goto stx_err;
  460.         toggle_variable(argv(1));
  461.         break;
  462.     }
  463.     
  464.     CASE( "define" ) {
  465.         if (in_init) {
  466.         if (argv(1) == NULL) {
  467.             init_message("macro number missing");
  468.             break;
  469.         }
  470.         m_define(argv(1), initf);
  471.         } else
  472.         if (m_define(argv(1), (FILE *)NULL))
  473.             return AC_REDRAW;
  474.         
  475.         break;
  476.     }
  477.         
  478.     CASE( "map" ) {
  479.         if (argv(2) == NULL) {
  480.         if (do_show("map", 1))
  481.             return AC_REDRAW;
  482.         break;
  483.         }
  484.  
  485.         do_map();
  486.         break;
  487.     }
  488.         
  489.     CASE( "cd" ) {
  490.         if (change_dir(argv(1), in_init))
  491.         init_message("chdir %s FAILED", argv(1));
  492.         
  493.         break;
  494.     }
  495.     
  496.     if (in_init) {
  497.         
  498.         CASE( "load" ) {
  499.         if (argv(1)) load_init_file(argv(1), (FILE **)NULL, 0);
  500.         break;
  501.         }
  502.  
  503.         CASE( "on" ) {
  504.         parse_on_to_end(initf);
  505.         break;
  506.         }
  507.         
  508.         CASE( "end" ) {
  509.         break;
  510.         }
  511.         
  512.         CASE( "sequence" ) {
  513.         return START_SEQUENCE;
  514.         }
  515.  
  516.         print_command("unknown command");
  517.         break;
  518.     }
  519.     
  520.     /* 
  521.      * commands only available from : command line 
  522.      */
  523.  
  524.     if (ok_val != AC_REDRAW) {
  525.         extern in_menu_mode;
  526.         
  527.         alt_cmd_key = lookup_command(sw_string, 
  528.                  in_menu_mode ? K_ONLY_MENU : K_ONLY_MORE);
  529.         if (alt_cmd_key != K_INVALID && alt_cmd_key != K_HELP)
  530.         return AC_KEYCMD;
  531.     }
  532.     
  533.     CASE( "q" ) {
  534.         break;
  535.     }
  536.     
  537.     CASE( "Q" ) {
  538.         return AC_QUIT;
  539.     }
  540.     
  541.     CASE( "q!" ) {
  542.         if (restore_bak())
  543.         return AC_QUIT;
  544.         break;
  545.     }
  546.     
  547.     CASE( "x" ) {
  548.         update_rc(current_group);
  549.         return AC_QUIT;
  550.     }
  551.     
  552.     CASE( "help" ) {
  553.         if (argv(1) == NULL)
  554.         display_help("help");
  555.         else
  556.         display_help(argv(1));
  557.         return AC_REDRAW;
  558.     }
  559.     
  560.     CASE( "man" ) {
  561.         char *manual;
  562.         group_header *orig_group;
  563.         int orig_layout, orig_fsort;
  564.         import int fmt_linenum, dont_sort_folders;
  565.         
  566.         manual = relative(lib_directory, "Manual");
  567.         if (!file_exist(manual, "fr")) {
  568.         manual = relative(db_directory, "Manual");
  569.         if (!file_exist(manual, "fr")) {
  570.             msg("Online manual is not available");
  571.             break;
  572.         }
  573.         }
  574.         orig_group = current_group;
  575.         orig_layout = fmt_linenum;
  576.         orig_fsort = dont_sort_folders;
  577.         
  578.         fmt_linenum = 4;
  579.         dont_sort_folders = 1;
  580.         
  581.         folder_menu(manual);
  582.         
  583.         fmt_linenum = orig_layout;
  584.         dont_sort_folders = orig_fsort;
  585.         init_group(orig_group);
  586.         
  587.         return AC_REDRAW;
  588.     }
  589.     
  590.     CASE( "sort" ) {
  591.         if ARG(1, "age")
  592.         unsort_articles(0);
  593.         else if (ARG(1, "no") || ARG(1, "arrival"))
  594.         unsort_articles(1);        
  595.         else
  596.         sort_articles();
  597.         return AC_REORDER;
  598.     }
  599.  
  600.     CASE( "unread" ) {
  601.         group_header *gh;
  602.         int ix = 1;
  603.         
  604.         if (argv(1) && (gh = lookup(argv(1))) != NULL)
  605.         ix = 2;
  606.         else
  607.         gh = current_group;
  608.         
  609.         if (restore_rc(gh, argv(ix) ? ARGVAL(ix) : 0))
  610.         if (gh == current_group) return AC_HEADER;
  611.         break;
  612.     }
  613.     
  614.     CASE( "dump" ) {
  615.         if (do_show(argv(1), 2))
  616.         return AC_REDRAW;
  617.         break;
  618.     }
  619.     
  620.     CASE( "show" ) {
  621.         if (do_show(argv(1), 2))
  622.         return AC_REDRAW;
  623.         break;
  624.     }
  625.  
  626.     CASE( "compile" ) {
  627.         import int do_kill_handling;
  628.         
  629.         clrdisp();
  630.         rm_kill_file();
  631.         free_kill_entries();
  632.         do_kill_handling = init_kill() && do_kill_handling;
  633.         return AC_REDRAW;
  634.     }
  635.  
  636.     CASE( "pwd" ) {
  637.         FILE *p = popen("exec pwd", "r");
  638.         char dir[FILENAME];
  639.         if (p) {
  640.         if (fgets(dir, FILENAME, p)) {
  641.             dir[strlen(dir) - 1] = NUL;
  642.             msg("%s", dir);
  643.         }
  644.         pclose(p);
  645.         }
  646.         break;
  647.     }
  648.  
  649.     CASE( "rmail" ) {
  650.         import char *mail_box;
  651.         group_header *orig_group;
  652.         
  653.         if (mail_box == NULL) {
  654.         msg("'mail' path not defined");
  655.         break;
  656.         }
  657.         
  658.         orig_group = current_group;
  659.         folder_menu(mail_box);
  660.         init_group(orig_group);
  661.  
  662.         return AC_REDRAW;
  663.     }
  664.     
  665.     CASE( "mkdir" ) {
  666.         char *dir, *run_mkdir();
  667.         char name_buf[FILENAME];
  668.     
  669.         if (dir = run_mkdir(argv(1), name_buf)) {
  670.         prompt("Change to %s", dir);
  671.         if (yes(0)) change_dir(dir, 0);
  672.         }
  673.         break;
  674.     }
  675.     
  676.     CASE( "sh" ) {
  677.         suspend_nn();
  678.         s_redraw = 0;
  679.         return AC_REDRAW;
  680.     }
  681.     
  682.     CASE( "admin" ) {
  683.         group_header *cur_group;
  684.         
  685.         cur_group = current_group;
  686.         no_raw();
  687.         clrdisp();
  688.         printf("\n\n\n\rADMINISTRATION MODE\r\n\n\n");
  689.         admin_mode((char *)NULL);
  690.         clrdisp();
  691.         raw();
  692.         init_group(cur_group);
  693.         return AC_REDRAW;
  694.     }
  695.     
  696.     CASE( "coredump" ) {
  697.         unset_raw();
  698.         abort();
  699.     }
  700.  
  701.     msg("unknown command: \"%s\"", argv(0));
  702.      }
  703.  
  704.     return ok_val;
  705.  
  706.  stx_err:
  707.     print_command("syntax error");
  708.     return ok_val;
  709. }
  710.  
  711.  
  712. static print_command(str)
  713. char *str;
  714. {
  715.     char **av;
  716.  
  717.     if (!in_init) {
  718.     msg(str);
  719.     return;
  720.     }
  721.     
  722.     printf("\r%s:", str);
  723.     for (av = argvec; *av; av++)
  724.         printf(" %s", *av);
  725.     putchar(NL);
  726. }
  727.  
  728.  
  729. static do_show(table, mode_arg)
  730. char *table;
  731. int mode_arg;
  732. {
  733.     if (in_init || table == NULL) return 0;
  734.     
  735.     no_raw();
  736.  
  737.     SWITCH( table ) {
  738.     
  739.     CASE( "kill" ) {
  740.         clrdisp();
  741.         dump_kill_list();
  742.         break;
  743.     }
  744.     
  745.     CASE( "groups" ) {
  746.     
  747.         clrdisp();
  748.         if ARG(mode_arg, "all")
  749.         group_overview(1);
  750.         else 
  751.         if ARG(mode_arg, "total")
  752.         group_overview(2);
  753.         else
  754.         if ARG(mode_arg, "unsub")
  755.         group_overview(3);
  756.         else
  757.         group_overview(0);
  758.  
  759.         break;
  760.     }
  761.     
  762.     CASE( "map" ) {
  763.  
  764.         if (argv(mode_arg) == NULL) {
  765.         init_message("map name missing");
  766.         goto err;
  767.         }
  768.         
  769.         if (argv(mode_arg)[0] == '#') {
  770.         clrdisp();
  771.         dump_multi_keys();
  772.         break;
  773.         }
  774.         
  775.         SWITCH( argv(mode_arg) ) {
  776.             
  777.         CASE( "key" ) {
  778.             clrdisp();
  779.             dump_global_map();
  780.             break;
  781.         }
  782.         CASE( "menu" ) {
  783.             clrdisp();
  784.             dump_key_map(menu_key_map, "menu", K_ONLY_MENU);
  785.             break;
  786.         }
  787.         CASE( "show" ) {
  788.             clrdisp();
  789.             dump_key_map(more_key_map, "show", K_ONLY_MORE);
  790.             break;
  791.         }
  792.  
  793.         init_message("unknown map '%s'", argv(mode_arg));
  794.         goto err;
  795.         /*NOTREACHED*/
  796.         }
  797.  
  798.         break;
  799.     }
  800.  
  801.     init_message("unknown table '%s'", table);
  802.     goto err;
  803.     /*NOTREACHED*/
  804.     }
  805.     
  806.     raw();    
  807.     return 1;
  808. err:    
  809.     raw();    
  810.     return 0;
  811. }
  812.  
  813.     
  814. static do_map()
  815. {
  816.     int code, map_menu, map_show;
  817.     
  818.     SWITCH( argv(1) ) {
  819.     
  820.     CASE( "key" ) {
  821.         if (argv(3) == NULL) break;
  822.         global_key_map[parse_key(argv(2))] = parse_key(argv(3));
  823.         return;
  824.     }
  825.     
  826.     if (argv(1)[0] == '#') {
  827.         char multi_buffer[16], *mb;
  828.         int i, parse_key();
  829.         
  830.         if (!isdigit(argv(1)[1])) break;
  831.         
  832.         for (i = 2, mb = multi_buffer; argv(i); i++)
  833.         *mb++ = (char)parse_key(argv(i));
  834.         *mb = NUL;
  835.         
  836.         enter_multi_key(K_function(argv(1)[1] - '0'),
  837.                 copy_str(multi_buffer));
  838.         
  839.         return;
  840.     }
  841.     
  842.     code = K_UNBOUND;
  843.     map_menu = map_show = 0;
  844.     
  845.     CASE( "menu" ) {
  846.         map_menu++;
  847.     }
  848.     CASE( "show" ) {
  849.         map_show++;
  850.     }
  851.     CASE( "both" ) {
  852.         map_menu++;
  853.         map_show++;
  854.     }
  855.     
  856.     if (map_menu) {
  857.         if (argv(3))
  858.         code = lookup_command(argv(3), K_ONLY_MENU);
  859.  
  860.         if (code == K_EQUAL_KEY) {
  861.         if (argv(4))
  862.             code = menu_key_map[parse_key(argv(4))];
  863.         else
  864.             goto mac_err;
  865.         } else
  866.         if (code == K_MACRO || code == K_ARTICLE_ID)
  867.         if (argv(4)) 
  868.             code |= atoi(argv(4));
  869.         else
  870.             goto mac_err;
  871.         
  872.         if (code != K_INVALID) {
  873.         menu_key_map[parse_key(argv(2))] = code;
  874.         if (!map_show) return;
  875.         }
  876.     }
  877.     
  878.     if (map_show) {
  879.         if (argv(3))
  880.         code = lookup_command(argv(3), K_ONLY_MORE);
  881.         
  882.         if (code == K_EQUAL_KEY) {
  883.         if (argv(4))
  884.             code = menu_key_map[parse_key(argv(4))];
  885.         else
  886.             goto mac_err;
  887.         } else
  888.         if (code == K_MACRO)
  889.         if (argv(4)) 
  890.             code |= atoi(argv(4));
  891.         else
  892.             goto mac_err;
  893.         
  894.         if (code != K_INVALID) {
  895.         more_key_map[parse_key(argv(2))] = code;
  896.         return;
  897.         }
  898.     }
  899.  
  900.     if (argv(4)) break;
  901.     
  902.     if (code == K_INVALID) {
  903.         init_message("unknown key command: %s", argv(3));
  904.         return;
  905.     }
  906.     }    
  907.  
  908.     print_command("syntax error");
  909.     return;
  910.     
  911.  mac_err:
  912.     print_command("last argument missing");
  913.     return;
  914. }
  915.  
  916. static parse_on_to_end(f)
  917. FILE *f;
  918. {
  919.     register char *cp;
  920.     char buf[256];
  921.     
  922.     if (argv(1) == NULL) goto on_err;
  923.  
  924.     SWITCH ( argv(1) ) {
  925.     
  926.     CASE( "entry" ) {
  927.         import char *dflt_enter_macro;
  928.         group_header *gh, *get_group_search();
  929.         char *macro;
  930.         int i;
  931.         
  932.         macro = parse_enter_macro(f, NL);
  933.         if (ARGTAIL) {
  934.         for (i = 2; argv(i); i++) {
  935.             start_group_search(argv(i));
  936.             while (gh = get_group_search())
  937.             gh->enter_macro = macro;
  938.         }
  939.         } else
  940.         dflt_enter_macro = macro;
  941.         break;
  942.     }
  943.  
  944. /*    CASE( "exit" ) {
  945.         import char *dflt_exit_macro;
  946.         
  947.         dflt_exit_macro = parse_enter_macro(f, NL);
  948.         break;
  949.     }
  950. */
  951.     CASE( "slow" ) {
  952.         import int terminal_speed, slow_speed;
  953.         
  954.         if (terminal_speed > (slow_speed / 10)) goto skip_to_end;
  955.         break;
  956.     }
  957.     
  958.     CASE( "fast" ) {
  959.         import int terminal_speed, slow_speed;
  960.         
  961.         if (terminal_speed <= (slow_speed / 10)) goto skip_to_end;
  962.         break;
  963.     }
  964.  
  965.     CASE( "term" ) {
  966.         extern char *term_name;
  967.  
  968.         if (argv(2) == NULL || strcmp(argv(2), term_name)) goto skip_to_end;
  969.         break;
  970.     }
  971.     
  972.     goto on_err;
  973.     }
  974.     return 0;
  975.     
  976. skip_to_end:
  977.     while (fgets(buf, 256, f) != NULL) {
  978.     for (cp = buf; *cp && isascii(*cp) && isspace(*cp); cp++);
  979.     if (strncmp(cp, "end", 3) == 0) return 0;
  980.     }
  981.     init_message("end missing (on %s)", argv(1));
  982.     
  983. on_err:
  984.     init_message("on `what'?");
  985. }
  986.  
  987. display_help(subject)
  988. char *subject;
  989. {
  990.     char file[FILENAME];
  991.     
  992.     strcpy(file, "help.");
  993.     strcpy(file+5, subject);
  994.     
  995.     display_file(file, CLEAR_DISPLAY | CONFIRMATION);
  996. }
  997.